#include "example.hpp"

#include <algorithm>
#include <cctype>
#include <numeric>
#include <sstream>
#include <stdexcept>

namespace example {

Calculator::Calculator()
    : name_("Calculator") {
}

Calculator::~Calculator() {
}

int Calculator::add(int a, int b) const {
    return a + b;
}

int Calculator::subtract(int a, int b) const {
    return a - b;
}

int Calculator::multiply(int a, int b) const {
    return a * b;
}

double Calculator::divide(double a, double b) const {
    if (b == 0.0) { throw std::invalid_argument("Division by zero"); }
    return a / b;
}

int Calculator::sum(const std::vector<int> &numbers) const {
    return std::accumulate(numbers.begin(), numbers.end(), 0);
}

std::string StringUtils::toUpper(const std::string &str) {
    std::string result = str;
    std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::toupper(c); });
    return result;
}

std::string StringUtils::toLower(const std::string &str) {
    std::string result = str;
    std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::tolower(c); });
    return result;
}

std::vector<std::string> StringUtils::split(const std::string &str, char delimiter) {
    std::vector<std::string> tokens;
    std::stringstream ss(str);
    std::string token;

    while (std::getline(ss, token, delimiter)) { tokens.push_back(token); }

    return tokens;
}

std::string StringUtils::trim(const std::string &str) {
    auto start = std::find_if_not(str.begin(), str.end(), [](unsigned char c) { return std::isspace(c); });
    auto end = std::find_if_not(str.rbegin(), str.rend(), [](unsigned char c) { return std::isspace(c); }).base();

    return (start < end) ? std::string(start, end) : std::string();
}

} // namespace example
